package com.system.web;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

import com.auth.domain.T_user;
import com.common.db.JsonVO;
import com.common.utils.DateUtil;
import com.common.utils.SystemConstants;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.log4j.Logger;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.json.simple.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

//@Service
//@Transactional
@Controller
@RequestMapping("/upload")

public class KindEditorUploadFile {

    protected Logger log = Logger.getLogger(KindEditorUploadFile.class);

    @Value(value = "${kindeditor.storage.image.path}")
    private String savePath; //D:\\ideaSource\\tajg\\src\\main\\resources\\static\\attached

    @Value(value = "${kindeditor.access.image.url}")
    private String saveUrl; //http://localhost:8080/attached/

    /**
     * system/t_file_upload/T_file_uploadCurd.jsp
     */
    @RequestMapping(value = "/toCommonFileUpload")
    public String toCommonFileUpload() {
        log.debug("------跳转到/WEB-INF/views/system/t_file_upload/commonFileUpload.jsp------");
        return "system/t_file_upload/commonFileUpload";
    }

    /**
     * system/t_file_upload/commonFileUpload2.jsp
     */
    @RequestMapping(value = "/toUploadOneFile2")
    public String toCommonFileUpload2() {
        log.debug("------跳转到/WEB-INF/views/system/t_file_upload/commonFileUpload2.jsp------");
        return "system/t_file_upload/commonFileUpload2";
    }

    /**
     * system/t_file_upload/commonFileUpload3.jsp
     */
    @RequestMapping(value = "/toUploadOneFile3")
    public String toCommonFileUpload3() {
        log.debug("------跳转到/WEB-INF/views/system/t_file_upload/commonFileUpload3.jsp------");
        return "system/t_file_upload/commonFileUpload3";
    }

    /**
     * 提供单个文件上传使用
     *
     * @param request
     * @param response
     * @throws Exception
     * @date 2021-5-12
     * @auth davexin
     */
    @PostMapping(value ="/uploadOneFile" )
    @ResponseBody
    public JsonVO uploadOneFile(HttpServletRequest request, HttpServletResponse response, @RequestParam("file1") MultipartFile file1) {
        JsonVO vo = new JsonVO();
        vo.setResult("error");
        vo.setJieguo(false);
        try {
            //*************************上传相关开始********************************************
            //判断file1不能为空;
            //String file1 = request.getParameter("file1");
            //request.
            if (file1 != null) {
                log.error("------本次上传文件名字=" + file1.getOriginalFilename());
                //保存文件
                //源文件名
                String oldFileName = file1.getOriginalFilename();
                //file类型
                String fileNameSuf = oldFileName.substring(oldFileName.lastIndexOf(".")).toLowerCase();
                //新的文件名：yyyyMMddHHmmss 格式；,把循环位置加上，防止程序执行过快，出现同名的文件名。
                String newFileName = DateUtil.getCurrDateTime() + fileNameSuf;
                // 文件保存路径
                //String filePath = request.getSession().getServletContext().getRealPath("/") + "upload/";
                log.error("------file=" + savePath + ";oldFileName=" + oldFileName + ";newFileName=" + newFileName);
                //如果文件名称中涵：.exe;.bat等可执行文件，提示失败；
                String allowFileType = "pdf,txt,doc,docx,xls,xlsx,ppt,txt,zip,rar,gz,bz2,gif,jpg,jpeg,png,bmp,swf,flv,mp3,mp4,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb";

                //判断文件后缀是否允许；
                if (!allowFileType.contains(fileNameSuf.substring(1))) {
                    log.error("------后缀为：" + fileNameSuf + "的文件类型不能上传！");
                    vo.setInfo("后缀为：" + fileNameSuf + "的文件类型不能上传！");
                    return vo;
                }

                //如果文件大于5000M,不保存该文件,返回失败；
                if (file1.getSize() > 1024 * 1024 * 5000) {
                    vo.setInfo("文件：" + savePath + " 大于5000M,不保存，请上传小于5000M的文件！");
                    log.error("------文件：" + savePath + " 大于5000M,不保存，请上传小于5000M的文件！");
                    return vo;
                } else {
                    // 转存文件
                    file1.transferTo(new File(savePath + newFileName));
                    vo.setResult("success");
                    vo.setJieguo(true);
                    vo.setInfo( oldFileName+"|"+newFileName );
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            vo.setInfo(e.getMessage());
        }
        return vo;
    }

    /**
     * 提供KindEditor作文件上传使用
     *
     * @param request
     * @param response
     * @throws Exception
     * @date 2021-5-12
     * @auth davexin
     */
    @PostMapping("/uploadFile")
    public void uploadFile(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath();
        PrintWriter writer = response.getWriter();

        try {
            //定义允许上传的文件扩展名
            HashMap<String, String> extMap = new HashMap<String, String>();
            extMap.put("image", "gif,jpg,jpeg,png,bmp");
            extMap.put("flash", "swf,flv");
            extMap.put("media", "swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb");
            extMap.put("file", "doc,docx,xls,xlsx,ppt,txt,zip,rar,gz,bz2");

            // 最大文件大小
            long maxSize = 1000000;
            response.setContentType("text/html; charset=UTF-8");

            if (!ServletFileUpload.isMultipartContent(request)) {
                writer.println("请选择文件。");
                return;
            }

            File uploadDir = new File(savePath);
            // 判断文件夹是否存在,如果不存在则创建文件夹
            if (!uploadDir.exists()) {
                uploadDir.mkdirs();
            }

            // 检查目录写权限
            if (!uploadDir.canWrite()) {
                writer.println("上传目录没有写权限。");
                return;
            }

            String dirName = request.getParameter("dir");
            if (dirName == null) {
                dirName = "image";
            }
            if (!extMap.containsKey(dirName)) {
                writer.println("目录名不正确。");
                return;
            }

            MultipartHttpServletRequest mRequest = (MultipartHttpServletRequest) request;
            Map<String, MultipartFile> fileMap = mRequest.getFileMap();
            String fileName = null;
            for (Iterator<Map.Entry<String, MultipartFile>> it = fileMap.entrySet().iterator(); it.hasNext(); ) {
                Map.Entry<String, MultipartFile> entry = it.next();
                MultipartFile mFile = entry.getValue();
                fileName = mFile.getOriginalFilename();
                // 检查文件大小
                if (mFile.getSize() > maxSize) {
                    writer.println("上传文件大小超过限制。");
                    return;
                }
                String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1);
                if (!Arrays.<String>asList(extMap.get(dirName).split(",")).contains(fileExt)) {
                    writer.println("上传文件扩展名是不允许的扩展名。\n只允许" + extMap.get(dirName) + "格式。");
                    return;
                }
                UUID uuid = UUID.randomUUID();
                String path = savePath + uuid.toString() + "." + fileExt;
                String url = saveUrl + uuid.toString() + "." + fileExt;

                BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(path));
                FileCopyUtils.copy(mFile.getInputStream(), outputStream);

                log.info("【提交图片】参数正确, url={}" + url);
                JSONObject obj = new JSONObject();
                obj.put("error", 0);
                obj.put("url", url);
                writer.println(obj.toString());
                log.info("存储图片路径=" + path);
                log.info("存储图片访问路径=" + url);
                //writer.println("{\"error\":0,\"url\":\"http://localhost:8080/attached/"+uuid.toString() + "." + fileExt+"\"}");
                log.info("【提交图片】参数正确,返回页面字符串如下：" + obj.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            writer.close();
        }
    }

    private String getError(String message) {
        JSONObject obj = new JSONObject();
        obj.put("error", 1);
        obj.put("message", message);
        return obj.toJSONString();
    }

    /**
     * 文件浏览处理
     *
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping("/uploadFileManager")
    public void uploadFileManager(HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setContentType("application/json; charset=UTF-8");
        PrintWriter out = response.getWriter();
        //根目录路径，可以指定绝对路径，比如 /var/www/attached/
        String rootPath = savePath;   //uploadPrefix + "/attached/";
        //根目录URL，可以指定绝对路径，比如 http://www.yoursite.com/attached/
        String rootUrl = saveUrl;  //request.getContextPath() + "/attached/";
        //图片扩展名
        String[] fileTypes = new String[]{"gif", "jpg", "jpeg", "png", "bmp"};

        String dirName = request.getParameter("dir"); //在image.js中dir=image;实际目录不需要再加这个；
        if (dirName != null) {
            if (!Arrays.<String>asList(new String[]{"image", "flash", "media", "file"}).contains(dirName)) {
                out.println("Invalid Directory name.");
                return;
            }
            //rootPath += dirName + "/"; //会多出一层image目录；不用再加上dir了；
            //rootUrl += dirName + "/";  //会多出一层image目录；不用再加上dir了；
            File saveDirFile = new File(rootPath);
            if (!saveDirFile.exists()) {
                saveDirFile.mkdirs();
            }
        }
        //根据path参数，设置各路径和URL
        String path = request.getParameter("path") != null ? request.getParameter("path") : "";
        String currentPath = rootPath + path;
        String currentUrl = rootUrl + path;
        String currentDirPath = path;
        String moveupDirPath = "";
        if (!"".equals(path)) {
            String str = currentDirPath.substring(0, currentDirPath.length() - 1);
            moveupDirPath = str.lastIndexOf("/") >= 0 ? str.substring(0, str.lastIndexOf("/") + 1) : "";
        }

        //排序形式，name or size or type
        String order = request.getParameter("order") != null ? request.getParameter("order").toLowerCase() : "name";

        //不允许使用..移动到上一级目录
        if (path.indexOf("..") >= 0) {
            out.println("Access is not allowed.");
            return;
        }
        //最后一个字符不是/
        if (!"".equals(path) && !path.endsWith("/")) {
            out.println("Parameter is not valid.");
            return;
        }
        //目录不存在或不是目录
        File currentPathFile = new File(currentPath);
        if (!currentPathFile.isDirectory()) {
            out.println("Directory does not exist.");
            return;
        }

        //遍历目录取的文件信息
        List<Hashtable> fileList = new ArrayList<Hashtable>();
        if (currentPathFile.listFiles() != null) {
            for (File file : currentPathFile.listFiles()) {
                Hashtable<String, Object> hash = new Hashtable<String, Object>();
                String fileName = file.getName();
                if (file.isDirectory()) {
                    hash.put("is_dir", true);
                    hash.put("has_file", (file.listFiles() != null));
                    hash.put("filesize", 0L);
                    hash.put("is_photo", false);
                    hash.put("filetype", "");
                } else if (file.isFile()) {
                    String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
                    hash.put("is_dir", false);
                    hash.put("has_file", false);
                    hash.put("filesize", file.length());
                    hash.put("is_photo", Arrays.<String>asList(fileTypes).contains(fileExt));
                    hash.put("filetype", fileExt);
                }
                hash.put("filename", fileName);
                hash.put("datetime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(file.lastModified()));
                fileList.add(hash);
            }
        }

        if ("size".equals(order)) {
            Collections.sort(fileList, new SizeComparator());
        } else if ("type".equals(order)) {
            Collections.sort(fileList, new TypeComparator());
        } else {
            Collections.sort(fileList, new NameComparator());
        }
        JSONObject result = new JSONObject();
        result.put("moveup_dir_path", moveupDirPath);
        result.put("current_dir_path", currentDirPath);
        result.put("current_url", currentUrl);
        result.put("total_count", fileList.size());
        result.put("file_list", fileList);

        out.println(result.toJSONString());
    }

    public class NameComparator implements Comparator {
        public int compare(Object a, Object b) {
            Hashtable hashA = (Hashtable) a;
            Hashtable hashB = (Hashtable) b;
            if (((Boolean) hashA.get("is_dir")) && !((Boolean) hashB.get("is_dir"))) {
                return -1;
            } else if (!((Boolean) hashA.get("is_dir")) && ((Boolean) hashB.get("is_dir"))) {
                return 1;
            } else {
                return ((String) hashA.get("filename")).compareTo((String) hashB.get("filename"));
            }
        }
    }

    public class SizeComparator implements Comparator {
        public int compare(Object a, Object b) {
            Hashtable hashA = (Hashtable) a;
            Hashtable hashB = (Hashtable) b;
            if (((Boolean) hashA.get("is_dir")) && !((Boolean) hashB.get("is_dir"))) {
                return -1;
            } else if (!((Boolean) hashA.get("is_dir")) && ((Boolean) hashB.get("is_dir"))) {
                return 1;
            } else {
                if (((Long) hashA.get("filesize")) > ((Long) hashB.get("filesize"))) {
                    return 1;
                } else if (((Long) hashA.get("filesize")) < ((Long) hashB.get("filesize"))) {
                    return -1;
                } else {
                    return 0;
                }
            }
        }
    }

    public class TypeComparator implements Comparator {
        public int compare(Object a, Object b) {
            Hashtable hashA = (Hashtable) a;
            Hashtable hashB = (Hashtable) b;
            if (((Boolean) hashA.get("is_dir")) && !((Boolean) hashB.get("is_dir"))) {
                return -1;
            } else if (!((Boolean) hashA.get("is_dir")) && ((Boolean) hashB.get("is_dir"))) {
                return 1;
            } else {
                return ((String) hashA.get("filetype")).compareTo((String) hashB.get("filetype"));
            }
        }
    }

}
